import pygame as SDL
from pygame.locals import *
import pENGINE, pACTORS, pAI
import random

class PauseState:
    """Just our basic pause screen.  Nice and simple."""
    def __init__(self,pong,screen):
        #set up all our objects
        self.paused = pENGINE.Sprite("data/paused.png",120,140)
        self.background = pENGINE.Background(screen,0,0,0)
        self.fps = SDL.time.Clock()
    def state(self, args):
        #get what we need from the arguments list
        pong = args['pong']
        screen = args['screen']
        
        #Start the fps timer
        self.fps.tick(30)
        
        #Get user input
        for event in SDL.event.get():
            if event.type == SDL.QUIT:
                sys.exit()
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    pong.StateMachine.pop()
                if event.key == K_y:
                    pong.StateMachine.pop()
                    pong.StateMachine.pop()
                if event.key == K_n:
                    pong.StateMachine.pop()
        
        
        #Draw everything to the screen!
        self.background.draw(screen)
        self.paused.draw(screen)


class MenuState:
    """We'll have a small little pong game going on in the background"""
    def __init__(self,screen):
        
        #Create our actors
        self.Paddle = pACTORS.MenuPaddle("data/paddle.png",20,200)
        self.Ball = pACTORS.Ball("data/ball.png",320,300)
        self.Enemy = pACTORS.MenuPaddle("data/paddle.png",620,290)
        self.overlayClouds = pACTORS.Clouds("data/overlayClouds.png")
        
        #And our background
        self.Background = pACTORS.Nebula("data/nebula.png")
        
        #Title screen and press start sprites
        self.title = pENGINE.Sprite("data/title.png",120,20)
        self.start = pENGINE.Sprite("data/enter.png",170,300)
        
        #don't forget the timer!
        self.fps = SDL.time.Clock()
        
    def state(self,args):
        pong = args['pong']
        screen = args['screen']
        
        self.fps.tick(30) #cap it at 30fps
        
        #Get the user input
        for event in SDL.event.get():
            if event.type == SDL.QUIT:
                sys.exit()
            elif event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    pong.StateMachine.pop()
                if event.key == K_RETURN:
                    pong.StateMachine.push(SinglePlayerState(pong,screen))
        
        #Update our actors
        self.Paddle.update(self.Ball)
        self.Ball.update()
        self.Enemy.update(self.Ball)
        
        #Check for the ball going off the top or bottom of the screen
        if self.Ball.y < 0:
            self.Ball.yVelocity = -self.Ball.yVelocity
        elif self.Ball.y > (pong.height-4):
            self.Ball.moveTo(self.Ball.x,self.Ball.y - 4)
            self.Ball.yVelocity = -self.Ball.yVelocity
            
        #Check if the ball goes off the screen from the left or right
        if self.Ball.x < 0:
            self.Ball.xVelocity = -self.Ball.xVelocity
            self.Ball.moveTo(320,300)
        if self.Ball.x > pong.width:
            self.Ball.xVelocity = -self.Ball.xVelocity
            self.Ball.moveTo(320,300)
        
        
        #Now check if the paddles are going off the screen
        if self.Paddle.y < 0:
            self.Paddle.y = 0
            self.Paddle.moveTo(self.Paddle.x,self.Paddle.y)
            
        if self.Paddle.y + self.Paddle.height > pong.height:
            self.Paddle.y = pong.height - self.Paddle.height
            self.Paddle.moveTo(self.Paddle.x,self.Paddle.y)
            
        
        #And the opponents too
        if self.Enemy.y < 0:
            self.Enemy.y = 0
            self.Enemy.moveTo(self.Enemy.x,self.Enemy.y)
            
        if self.Enemy.y + self.Enemy.height > pong.height:
            self.Enemy.y = pong.height - self.Enemy.height
            self.Enemy.moveTo(self.Enemy.x,self.Enemy.y)
            
            
        #Now for the collision of the paddles
        if self.Paddle.rect.colliderect(self.Ball.rect)==True:
            self.Ball.xVelocity = -self.Ball.xVelocity
            
        if self.Enemy.rect.colliderect(self.Ball.rect)==True:
            self.Ball.xVelocity = -self.Ball.xVelocity
        
        
        #Draw the background
        self.Background.draw(screen)
        self.overlayClouds.draw(screen)
        
        #And the actors
        self.Paddle.draw(screen)
        self.Ball.draw(screen)
        self.Enemy.draw(screen)
        
        #Now we draw the title and the 'Press Start' sprites
        self.title.draw(screen)
        self.start.draw(screen)


class SinglePlayerState:
    def __init__(self,pong,screen):
        
        #Add the sprites
        self.Paddle = pACTORS.Paddle("data/paddle.png",20,200)
        self.Ball = pACTORS.Ball("data/ball.png",320,300)
        self.Enemy = pACTORS.Enemy("data/paddle.png",620,290)
        self.Background = pACTORS.Nebula("data/nebula.png")
        self.overlayClouds = pACTORS.Clouds("data/overlayclouds.png")
        self.Score = pACTORS.ScoreChart("0:0",(0,0,255),pong.width)
        
        #Set vars for dealing with shooting the ball
        self.ballcatch = True
        self.loser = 1
        self.wait = range(60)
        
        #Now the score counters
        self.pScore = 0
        self.eScore = 0
        
        #FPS Timer
        self.fps = SDL.time.Clock()
        
    def state(self, args):
        pong = args['pong']
        screen = args['screen']
        
        self.fps.tick(30) #limit the fps to 30
        
        #Get the input from the user
        for event in SDL.event.get():
            if event.type == SDL.QUIT:
                sys.exit()
            
            elif event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    pong.StateMachine.push(PauseState(pong,screen))
                    
                if event.key == K_w:
                    self.Paddle.vUp()
                    
                if event.key == K_s:
                    self.Paddle.vDown()
                    
                if event.key == K_SPACE:
                    self.ballcatch = False
                    
            elif event.type == KEYUP:
                if event.key == K_w:
                    self.Paddle.vDown()
                    
                if event.key == K_s:
                    self.Paddle.vUp()
        
        #update the paddle
        self.Paddle.update()
        
        #Now check for the ballcatch
        
        if self.ballcatch == True:
            if self.loser == 1:
                self.Ball.moveTo(40,self.Paddle.y+18)
                
            else:
                self.Ball.moveTo(600,self.Enemy.y+18)
                
                if len(self.wait)==0:
                    self.ballcatch = False
                    self.wait = range(60)
                else:
                    self.wait.pop()
        else:
            self.Ball.update()
        
        #update the score and the enmy paddle
        self.Score.update("%i:%i" % (self.pScore,self.eScore),pong.width)
        self.Enemy.update(self.Ball,self.Paddle)
        
        #Check to see if the ball is going off the top or bottom of the screen
        if self.Ball.y < 0:
            self.Ball.yVelocity = -self.Ball.yVelocity
        elif self.Ball.y > (pong.height-4):
            self.Ball.moveTo(self.Ball.x,self.Ball.y - 4)
            self.Ball.yVelocity = -self.Ball.yVelocity
        
        
        #Find if a player has won a round
        if self.Ball.x < 0:
            self.eScore += 1
            self.Ball.xVelocity = -self.Ball.xVelocity
            self.ballcatch = True
            self.loser = 1
        if self.Ball.x > pong.width:
            self.pScore += 1
            self.Ball.xVelocity = -self.Ball.xVelocity
            self.ballcatch = True
            self.loser = 2
            self.Enemy.state.push(pAI.Shoot())
            
        
        #Check if the paddle is going off the screen
        if self.Paddle.y < 0:
            self.Paddle.y = 0
            self.Paddle.moveTo(self.Paddle.x,self.Paddle.y)
        if self.Paddle.y + self.Paddle.height > pong.height:
            self.Paddle.y = pong.height - self.Paddle.height
            self.Paddle.moveTo(self.Paddle.x,self.Paddle.y)
        
        #Do the oponent too
        if self.Enemy.y < 0:
            self.Enemy.y = 0
            self.Enemy.moveTo(self.Enemy.x, self.Enemy.y)
        if self.Enemy.y + self.Enemy.height > pong.height:
            self.Enemy.y = pong.height - self.Enemy.height
            self.Enemy.moveTo(self.Enemy.x, self.Enemy.y)
        
        
        #And the collision detection
        if self.Paddle.rect.colliderect(self.Ball.rect)==True:
            self.Ball.xVelocity = -self.Ball.xVelocity
        if self.Enemy.rect.colliderect(self.Ball.rect)==True:
            self.Ball.xVelocity = -self.Ball.xVelocity
        
        
        #Now to render everything
        self.Background.draw(screen)
        self.overlayClouds.draw(screen)
        self.Paddle.draw(screen)
        self.Ball.draw(screen)
        self.Enemy.draw(screen)
        self.Score.draw(screen)




class MultiPlayerState:
    def __init__(self,pong,screen):
        
        #Add the sprites
        self.Left = pACTORS.Paddle("data/paddle.png",20,200)
        self.Ball = pACTORS.Ball("data/ball.png",320,300)
        self.Right = pACTORS.Paddle("data/paddle.png",620,290)
        
        self.Background = pACTORS.Nebula("data/nebula.png")
        self.overlayClouds = pACTORS.Clouds("data/overlayclouds.png")
        
        self.Score = pACTORS.ScoreChart("0:0",(0,0,255),pong.width)
        
        #Set vars for dealing with shooting the ball
        self.ballcatch = True
        self.loser = random.randrange(2)
        
        if self.loser == 1: #If player 2 starts with the ball, have the ball
            #launch towards player 1, rather than rebounding back at itself
            self.Ball.xVelocity = -self.Ball.xVelocity
        
        #Now the score counters
        self.pScore = 0
        self.eScore = 0
        
        #FPS Timer
        self.fps = SDL.time.Clock()
        
    def state(self, args):
        pong = args['pong']
        screen = args['screen']
        
        self.fps.tick(30) #limit the fps to 30
        
        #Get the input from the user
        for event in SDL.event.get():
            if event.type == SDL.QUIT:
                sys.exit()
            
            elif event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    pong.StateMachine.push(PauseState(pong,screen))
                    
                if event.key == K_w:    #Left player key bindings
                    self.Left.vUp()
                    
                if event.key == K_s:
                    self.Left.vDown()
                    
                if event.key == K_q:
                    if self.loser == 0:
                        self.ballcatch = False
                
                if event.key == K_o:    #Right player key bindings
                    self.Right.vUp()
                    
                if event.key == K_l:
                    self.Right.vDown()
                
                if event.key == K_p:
                    if self.loser == 1:
                        self.ballcatch = False
                    
            elif event.type == KEYUP:
                if event.key == K_w:    #Left player key bindings
                    self.Left.vDown()
                    
                if event.key == K_s:
                    self.Left.vUp()
                
                if event.key == K_o:
                    self.Right.vDown()
                    
                if event.key == K_l:
                    self.Right.vUp()
        
        #update the paddle
        self.Left.update()
        self.Right.update()
        
        #Now check for the ballcatch
        
        if self.ballcatch == True:
            if self.loser == 0:
                self.Ball.moveTo(40,self.Left.y+18)
                
            else:
                self.Ball.moveTo(600,self.Right.y+18)
        else:
            self.Ball.update()
        
        #update the score
        self.Score.update("%i:%i" % (self.pScore,self.eScore),pong.width)
        
        #Check to see if the ball is going off the top or bottom of the screen
        if self.Ball.y < 0:
            self.Ball.yVelocity = -self.Ball.yVelocity
        elif self.Ball.y > (pong.height-4):
            self.Ball.moveTo(self.Ball.x,self.Ball.y - 4)
            self.Ball.yVelocity = -self.Ball.yVelocity
        
        
        #Find if a player has won a round
        if self.Ball.x < 0:
            self.eScore += 1
            self.Ball.xVelocity = -self.Ball.xVelocity
            self.ballcatch = True
            self.loser = 0
        if self.Ball.x > pong.width:
            self.pScore += 1
            self.Ball.xVelocity = -self.Ball.xVelocity
            self.ballcatch = True
            self.loser = 1
            
        
        #Check if the paddle is going off the screen
        if self.Left.y < 0:
            self.Left.y = 0
            self.Left.moveTo(self.Left.x,self.Left.y)
        if self.Left.y + self.Left.height > pong.height:
            self.Left.y = pong.height - self.Left.height
            self.Left.moveTo(self.Left.x,self.Left.y)
        
        #Do the oponent too
        if self.Right.y < 0:
            self.Right.y = 0
            self.Right.moveTo(self.Right.x, self.Right.y)
        if self.Right.y + self.Right.height > pong.height:
            self.Right.y = pong.height - self.Right.height
            self.Right.moveTo(self.Right.x, self.Right.y)
        
        
        #And the collision detection
        if self.Left.rect.colliderect(self.Ball.rect)==True:
            self.Ball.xVelocity = -self.Ball.xVelocity
        if self.Right.rect.colliderect(self.Ball.rect)==True:
            self.Ball.xVelocity = -self.Ball.xVelocity
        
        
        #Now to render everything
        self.Background.draw(screen)
        self.overlayClouds.draw(screen)
        self.Left.draw(screen)
        self.Ball.draw(screen)
        self.Right.draw(screen)
        self.Score.draw(screen)
